package fr.neyb.bernouilli.common.math;

import java.util.Comparator;

import fr.neyb.bernouilli.common.tools.CheckTools;

public class MyMathTools {
	private MyMathTools() {
	}

	private static class StdComp<T extends Comparable<T>> implements
			Comparator<T> {
		@Override
		public int compare(T o1, T o2) {
			return o1.compareTo(o2);
		}
	}

	private static class Reverse<T> implements Comparator<T> {
		Comparator<T> orig;

		public Reverse(Comparator<T> orig) {
			this.orig = orig;
		}

		@Override
		public int compare(T o1, T o2) {
			return -1 * orig.compare(o1, o2);
		}
	}

	private static final Comparator<?> stdComp = new StdComp<>();
	private static final Comparator<?> ReverseStdComp = new Reverse<>(stdComp);

	@SuppressWarnings("unchecked")
	public static <T extends Comparable<T>> T min(T... ts) {
		return min((Comparator<T>) stdComp, ts);
	}

	@SuppressWarnings("unchecked")
	public static <T extends Comparable<T>> T max(T... ts) {
		return min((Comparator<T>) ReverseStdComp, ts);
	}
	
	@SafeVarargs
	public static <T> T max(Comparator<T> comparator, T... ts) {
		return min(new Reverse<>(comparator), ts);
	}

	@SafeVarargs
	public static <T> T min(Comparator<T> comparator, T... ts) {
		CheckTools.checkNotNull((Object) ts);
		CheckTools.checkNotNull((Object[]) ts);
		if (ts.length > 0) {
			T min = ts[0];
			for (T t : ts)
				if (comparator.compare(t, min) < 0)
					min = t;
			return min;
		} else {
			return null;
		}
	}

}
